package controller

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"backEnd/common"
	"backEnd/model"
	"backEnd/util"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
)

func PhoneRegister(ctx *gin.Context) { // 发送验证码
	var (
		DB          = common.GetDB()
		requestUser = model.User{}
	)
	ctx.ShouldBindJSON(&requestUser)
	telephone := requestUser.Telephone

	//判断手机号码是否存在
	if util.IsTelephoneExists(DB, telephone) {
		ctx.JSON(400, gin.H{"msg": "该手机号已经注册"})
		return
	}
	//生成随机数字字符串
	VerificationCode := model.VerificationCode{
		Telephone: telephone,
		Code:      util.RandNumString(6),
	}
	//发送验证码
	common.SendSms(telephone, VerificationCode.Code)
	//数据库中创建验证码对象
	DB.Create(&VerificationCode)
	//赋值用于token识别
	requestUser.ID = 0
	//发放token
	token, err := common.ReleaseToken(requestUser, time.Now().Add(5*time.Minute))
	if err != nil {
		ctx.JSON(500, gin.H{"msg": "token发放失败"})
		log.Printf("token generate error: %v", err)
		return
	}
	ctx.JSON(200, gin.H{
		"msg":   "验证码发送成功",
		"token": token,
	})
}

func Verification(ctx *gin.Context) { // 验证码验证
	var (
		verification, _  = ctx.Get("verificationCode")
		DB               = common.GetDB()
		VerificationCode = verification.(model.VerificationCode)
	)
	ctx.ShouldBindJSON(&VerificationCode)

	var (
		code      = VerificationCode.Code
		telephone = VerificationCode.Telephone
		password  = VerificationCode.Password
	)

	if result := DB.Model(&model.VerificationCode{}).Where("code = ? AND telephone = ?", code, telephone); result.Error != nil {
		// 发生错误，进行相应的容错处理
		ctx.JSON(500, gin.H{
			"msg": "查找验证码失败",
			"err": result.Error,
		})
		return
	} else if result.RecordNotFound() {
		// 没有更新任何记录，说明验证码或电话号码错误
		ctx.JSON(401, gin.H{
			"msg": "验证码或电话号码错误",
		})
		return
	}

	//给密码加个密
	hasePassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		ctx.JSON(500, gin.H{"msg": "加密失败"})
		return
	}

	//随机字符串命名
	userName := "用户" + util.RandString(8)

	//定义新用户
	newUser := model.User{
		UserName:  userName,
		Avatar:    "https://photos-1313896513.cos.ap-nanjing.myqcloud.com/img/head.png", //腾讯云上的默认头像
		Telephone: telephone,
		Password:  string(hasePassword),
		Detail: model.UserDetail{
			Tel: telephone,
		},
	}

	fmt.Print(newUser, "\n")

	//判断数据库中该用户是否存在
	var count int
	DB.Model(&model.User{}).Where("telephone = ?", newUser.Telephone).Count(&count)
	if count == 0 {
		//创建新用户
		if err := DB.Create(&newUser).Error; err != nil {
			ctx.JSON(500, gin.H{
				"msg": "创建新用户失败",
			})
			fmt.Print(err.Error(), "\n")
			return
		}
	} else {
		ctx.JSON(500, gin.H{
			"msg": "用户已存在",
		})
	}

	//返回结果
	ctx.JSON(201, gin.H{"msg": "注册成功！"})
}

func Login(ctx *gin.Context) { // 登录
	var (
		DB          = common.GetDB()
		requestUser = model.User{}
		user        = model.User{}
	)

	ctx.ShouldBindJSON(&requestUser)
	if err := DB.Where("telephone = ?", requestUser.Telephone).First(&user).Error; err != nil {
		ctx.JSON(500, gin.H{
			"msg": "用户查询失败",
		})
		return
	}
	//判断密码是否正确
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(requestUser.Password)); err != nil {
		ctx.JSON(401, gin.H{"msg": "密码错误"})
		return
	}

	//发放token
	token, err := common.ReleaseToken(user, time.Now().Add(7*24*time.Hour))
	if err != nil {
		ctx.JSON(500, gin.H{"msg": "token发放失败"})
		log.Printf("token generate error: %v", err)
		return
	}

	user.Password = ""

	//返回结果
	ctx.JSON(200, gin.H{
		"token": token,
		"user":  user,
	})
}

func Info(ctx *gin.Context) { // 依据token查询用户信息
	middleUser, _ := ctx.Get("user")
	user := middleUser.(model.User)
	user.Password = ""
	ctx.JSON(http.StatusOK, gin.H{
		"user": user,
	})
}

func UpdateUser(ctx *gin.Context) { // 更新信息
	var (
		updatedUser   model.User
		user          model.User
		middleUser, _ = ctx.Get("user")
		DB            = common.GetDB()
		userId        = middleUser.(model.User).ID
	)

	ctx.ShouldBindJSON(&updatedUser)
	if err := DB.Where("id = ?", userId).First(&user).Error; err != nil {
		ctx.JSON(500, gin.H{
			"msg": "user查询失败",
			"err": err,
		})
	}

	//给更新以后的头像加上url前缀
	if updatedUser.Avatar != "" {
		updatedUser.Avatar = util.GenerateImgUrl(updatedUser.Avatar)
	}

	// 更新用户信息
	user.UserName = util.GetUpdatedValue(user.UserName, updatedUser.UserName)
	user.Avatar = util.GetUpdatedValue(user.Avatar, updatedUser.Avatar)
	user.Detail.Weixin = util.GetUpdatedValue(user.Detail.Weixin, updatedUser.Detail.Weixin)
	user.Detail.QQ = util.GetUpdatedValue(user.Detail.QQ, updatedUser.Detail.QQ)
	user.Detail.Tel = util.GetUpdatedValue(user.Detail.Tel, updatedUser.Telephone)
	user.Detail.Introduce = util.GetUpdatedValue(user.Detail.Introduce, updatedUser.Detail.Introduce)

	if err := DB.Save(&user).Error; err != nil {
		ctx.JSON(500, gin.H{
			"msg": "user保存失败",
			"err": err,
		})
	}

	user.Password = ""

	fmt.Print("修改后的user:", user, "\n")

	ctx.JSON(200, gin.H{
		"msg":  "修改成功！",
		"user": user,
	})
}

func UpdatePassword(ctx *gin.Context) { // 更新密码
	var (
		middleUser, _   = ctx.Get("user")
		DB              = common.GetDB()
		userId          = middleUser.(model.User).ID
		requestPassword = make(map[string]string)
		user            model.User
	)

	ctx.ShouldBindJSON(&requestPassword)
	newPassword := requestPassword["new_password"]
	oldpassword := requestPassword["old_password"]

	// 查询原始密码
	if err := DB.Model(&model.User{}).Where("id = ?", userId).First(&user).Error; err != nil {
		ctx.JSON(500, gin.H{"msg": "数据库查询出错"})
	}

	//判断原始密码是否正确
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldpassword)); err != nil {
		ctx.JSON(401, gin.H{"msg": "旧密码错误"})
		return
	}

	//给密码加个密
	hasePassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		ctx.JSON(500, gin.H{"msg": "加密失败"})
		return
	}

	user.Password = string(hasePassword)

	if err := DB.Save(&user).Error; err != nil {
		ctx.JSON(500, gin.H{
			"msg": "user保存失败",
			"err": err,
		})
	}

	user.Password = ""

	fmt.Print("修改后的user:", user, "\n")

	ctx.JSON(200, gin.H{
		"msg":  "修改成功！",
	})
}

func GetPublishedProductsByUser(ctx *gin.Context) { // published
	var (
		DB              = common.GetDB()
		user, _         = ctx.Get("user")
		productIDs      []int
		count           int
		ProductCoverImg model.ProductCoverImg
		ProductDetail   model.ProductDetail
		Products        []model.Product
	)

	// 取出所有该用户发布的商品，包括已下架、过期的
	if err := DB.Model(&model.Product{}).Where("seller_id = ?", user.(model.User).ID).Pluck("product_id", &productIDs).Count(&count).Find(&Products).Error; err != nil {
		ctx.JSON(500, gin.H{
			"msg": "无法查询到商品",
			"err": err,
		})
		return
	}

	// 填充封面图片
	for i, productId := range productIDs {
		if err := DB.Where("product_id = ?", productId).First(&ProductCoverImg).Error; err != nil {
			if err == gorm.ErrRecordNotFound {
				// 记录不存在，填充空值
				ProductCoverImg = model.ProductCoverImg{ProductCoverImg: ""}
			} else {
				fmt.Print("封面图片填充失败,出错商品id:", productId)
				ctx.JSON(500, gin.H{
					"msg": "封面图片填充失败"})
				return
			}
		}
		Products[i].ProductCoverImg = make([]model.ProductCoverImg, 1)
		Products[i].ProductCoverImg[0].ProductCoverImg = ProductCoverImg.ProductCoverImg
	}

	// 填充商品详情
	for i, productId := range productIDs {
		ProductDetail = model.ProductDetail{}
		if err := DB.Where("id = ? AND timestamp IS NOT NULL", productId).First(&ProductDetail).Error; err != nil {
			if err == gorm.ErrRecordNotFound {
				// 记录不存在，填充空值
				ProductDetail = model.ProductDetail{}
			} else {
				fmt.Print("商品详情填充失败,出错商品id:", productId)
				ctx.JSON(500, gin.H{
					"msg": "商品详情填充失败"})
				return
			}
		}
		Products[i].Detail = ProductDetail
	}

	ctx.JSON(200, gin.H{
		"count":    count,
		"products": Products,
	})
}

func Authentication(ctx *gin.Context) { //实名认证
	var (
		middleUser, _    = ctx.Get("user")
		DB               = common.GetDB()
		VerificationUser = model.VerificationUser{}
	)

	ctx.ShouldBindJSON(&VerificationUser)

	ImgUrl := util.GenerateImgUrl(VerificationUser.FileName)
	//定义新用户
	newAuthentication := model.VerificationUser{
		UserID:   middleUser.(model.User).ID,
		FileName: ImgUrl,
	}

	fmt.Print(newAuthentication, "\n")

	//判断数据库中该用户是否存在
	var count int
	DB.Model(&model.VerificationUser{}).Where("user_id = ? AND Status = ?", newAuthentication.UserID, 0).Count(&count)
	if count == 0 {
		//创建记录
		if err := DB.Create(&newAuthentication).Error; err != nil {
			ctx.JSON(500, gin.H{
				"msg": "创建新审核失败",
			})
			fmt.Print(err.Error(), "\n")
			return
		}
	} else {
		ctx.JSON(500, gin.H{
			"msg": "您的审核记录还在审核中，请不要重复提交",
		})
	}

	//返回结果
	ctx.JSON(201, gin.H{"msg": "认证请求提交成功！"})
}
